<template>
  <div class="app">
    <div class="particles-container" ref="particlesContainer"></div>
    
    <div class="header">
      <h1>🌍 全球实时地震监控</h1>
      <p>显示最近24小时内全球地震数据 (数据来源: USGS)</p>
    </div>
    
    <div class="stats-panel" v-if="stats">
      <div class="stat-card">
        <h3>地震总数</h3>
        <div class="value">{{ stats.total }}</div>
      </div>
      <div class="stat-card">
        <h3>最大震级</h3>
        <div class="value">{{ stats.maxMagnitude.toFixed(1) }}</div>
      </div>
      <div class="stat-card">
        <h3>平均震级</h3>
        <div class="value">{{ stats.avgMagnitude.toFixed(1) }}</div>
      </div>
      <div class="stat-card">
        <h3>最近地震</h3>
        <div class="value">{{ stats.mostRecent }}</div>
      </div>
    </div>
    
    <div id="map" ref="mapContainer"></div>
    
    <div class="info-panel">
      <h2>地震信息</h2>
      <div v-if="selectedEarthquake">
        <div class="magnitude-info">
          <h3>{{ selectedEarthquake.properties.place }}</h3>
          <p class="magnitude">震级: <strong>{{ selectedEarthquake.properties.mag.toFixed(1) }}</strong></p>
          <p><span>时间:</span> <span>{{ formatTime(selectedEarthquake.properties.time) }}</span></p>
          <p><span>相对时间:</span> <span>{{ formatRelativeTime(selectedEarthquake.properties.time) }}</span></p>
          <p><span>深度:</span> <span>{{ selectedEarthquake.geometry.coordinates[2] }} km</span></p>
          <p><span>海啸预警:</span> <span>{{ selectedEarthquake.properties.tsunami ? '是' : '否' }}</span></p>
          <p><span>感知报告:</span> <span>{{ selectedEarthquake.properties.felt || '无报告' }}</span></p>
          <p><span>重要性:</span> <span>{{ selectedEarthquake.properties.sig || 'N/A' }}/1000</span></p>
          <p><span>经度:</span> <span>{{ selectedEarthquake.geometry.coordinates[1].toFixed(4) }}</span></p>
          <p><span>纬度:</span> <span>{{ selectedEarthquake.geometry.coordinates[0].toFixed(4) }}</span></p>
        </div>
      </div>
      <div v-else>
        <p v-if="loading" class="loading">正在加载地震数据...</p>
        <p v-else-if="earthquakeData">点击地图上的标记查看地震详细信息</p>
        <div v-else class="error">加载地震数据时出错: {{ error }}</div>
      </div>
    </div>
  </div>
</template>

<script>
import { ref, onMounted, onUnmounted } from 'vue'
import * as L from 'leaflet'

export default {
  name: 'EarthquakeMonitor',
  setup() {
    // 响应式数据
    const mapContainer = ref(null)
    const particlesContainer = ref(null)
    const map = ref(null)
    const earthquakeData = ref(null)
    const selectedEarthquake = ref(null)
    const loading = ref(true)
    const error = ref(null)
    const stats = ref(null)
    
    let earthquakeLayer = null
    let refreshInterval = null
    
    // 地震数据URL
    const earthquakeUrl = 'https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_day.geojson'
    
    // 震级颜色映射
    const getMarkerColor = (magnitude) => {
      return magnitude > 7 ? '#800026' :
             magnitude > 6 ? '#BD0026' :
             magnitude > 5 ? '#E31A1C' :
             magnitude > 4 ? '#FC4E2A' :
             magnitude > 3 ? '#FD8D3C' :
             magnitude > 2 ? '#FEB24C' :
             magnitude > 1 ? '#FED976' :
                            '#FFEDA0'
    }
    
    // 根据震级确定标记大小
    const getMarkerSize = (magnitude) => {
      return Math.max(magnitude * 4, 8)
    }
    
    // 格式化时间
    const formatTime = (timestamp) => {
      const date = new Date(timestamp)
      return date.toLocaleString('zh-CN', {
        year: 'numeric',
        month: 'long',
        day: 'numeric',
        hour: '2-digit',
        minute: '2-digit',
        second: '2-digit',
        timeZoneName: 'short'
      })
    }
    
    // 格式化时间为相对时间
    const formatRelativeTime = (timestamp) => {
      const now = new Date().getTime()
      const diff = now - timestamp
      const minutes = Math.floor(diff / 60000)
      const hours = Math.floor(diff / 3600000)
      const days = Math.floor(diff / 86400000)
      
      if (days > 0) {
        return `${days}天前`
      } else if (hours > 0) {
        return `${hours}小时前`
      } else {
        return `${minutes}分钟前`
      }
    }
    
    // 创建粒子背景效果
    const createParticles = () => {
      const particleCount = 50
      
      for (let i = 0; i < particleCount; i++) {
        const particle = document.createElement('div')
        particle.classList.add('particle')
        
        // 随机大小
        const size = Math.random() * 10 + 2
        particle.style.width = `${size}px`
        particle.style.height = `${size}px`
        
        // 随机位置
        particle.style.left = `${Math.random() * 100}%`
        particle.style.top = `${Math.random() * 100}%`
        
        // 随机颜色
        const colors = [
          'rgba(52, 152, 219, 0.6)',
          'rgba(46, 204, 113, 0.6)',
          'rgba(231, 76, 60, 0.6)',
          'rgba(155, 89, 182, 0.6)'
        ]
        particle.style.background = colors[Math.floor(Math.random() * colors.length)]
        
        // 随机动画延迟和持续时间
        const delay = Math.random() * 15
        const duration = 15 + Math.random() * 10
        particle.style.animationDelay = `${delay}s`
        particle.style.animationDuration = `${duration}s`
        
        particlesContainer.value.appendChild(particle)
      }
    }
    
    // 计算统计数据
    const calculateStats = (features) => {
      if (features.length === 0) {
        return {
          total: 0,
          maxMagnitude: 0,
          avgMagnitude: 0,
          mostRecent: 'N/A'
        }
      }
      
      const magnitudes = features.map(f => f.properties.mag)
      const maxMagnitude = Math.max(...magnitudes)
      const avgMagnitude = magnitudes.reduce((a, b) => a + b, 0) / magnitudes.length
      
      // 找到最近的地震
      const mostRecentFeature = features.reduce((latest, current) => {
        return current.properties.time > latest.properties.time ? current : latest
      })
      const mostRecent = formatRelativeTime(mostRecentFeature.properties.time)
      
      return {
        total: features.length,
        maxMagnitude: maxMagnitude,
        avgMagnitude: avgMagnitude,
        mostRecent: mostRecent
      }
    }
    
    // 创建自定义标记
    const createEarthquakeMarker = (feature, latlng) => {
      const magnitude = feature.properties.mag
      const place = feature.properties.place
      const time = feature.properties.time
      
      return L.circleMarker(latlng, {
        radius: getMarkerSize(magnitude),
        fillColor: getMarkerColor(magnitude),
        color: "#000",
        weight: 1,
        opacity: 1,
        fillOpacity: 0.8,
        className: 'earthquake-marker'
      }).bindPopup(`
        <div class="magnitude-popup">
          <div class="magnitude-info">
            <h3>地震详情</h3>
            <p class="magnitude">震级: ${magnitude.toFixed(1)}</p>
            <p class="place">${place}</p>
            <p class="time">${formatTime(time)}</p>
            <p>深度: ${feature.geometry.coordinates[2]} km</p>
            <p>发生时间: ${formatRelativeTime(time)}</p>
          </div>
        </div>
      `).on('click', () => {
        selectedEarthquake.value = feature
      })
    }
    
    // 添加图例
    const addLegend = () => {
      const legend = L.control({ position: 'bottomright' })
      
      legend.onAdd = function() {
        const div = L.DomUtil.create('div', 'legend')
        div.innerHTML = `
          <h4>震级图例</h4>
          <div class="legend-item">
            <span class="legend-color" style="background: #800026"></span>
            <span class="legend-label">7+ 级</span>
          </div>
          <div class="legend-item">
            <span class="legend-color" style="background: #BD0026"></span>
            <span class="legend-label">6-7 级</span>
          </div>
          <div class="legend-item">
            <span class="legend-color" style="background: #E31A1C"></span>
            <span class="legend-label">5-6 级</span>
          </div>
          <div class="legend-item">
            <span class="legend-color" style="background: #FC4E2A"></span>
            <span class="legend-label">4-5 级</span>
          </div>
          <div class="legend-item">
            <span class="legend-color" style="background: #FD8D3C"></span>
            <span class="legend-label">3-4 级</span>
          </div>
          <div class="legend-item">
            <span class="legend-color" style="background: #FEB24C"></span>
            <span class="legend-label">2-3 级</span>
          </div>
          <div class="legend-item">
            <span class="legend-color" style="background: #FFEDA0"></span>
            <span class="legend-label">0-2 级</span>
          </div>
        `
        return div
      }
      
      legend.addTo(map.value)
    }
    
    // 获取地震数据
    const fetchEarthquakeData = async () => {
      try {
        loading.value = true
        error.value = null
        
        const response = await fetch(earthquakeUrl)
        if (!response.ok) {
          throw new Error('数据加载失败')
        }
        
        const data = await response.json()
        earthquakeData.value = data
        
        // 计算并显示统计数据
        stats.value = calculateStats(data.features)
        
        // 清除旧图层
        if (earthquakeLayer) {
          map.value.removeLayer(earthquakeLayer)
        }
        
        // 创建新图层
        earthquakeLayer = L.geoJSON(data, {
          pointToLayer: createEarthquakeMarker
        }).addTo(map.value)
        
        // 调整地图视图以适应所有标记
        if (data.features.length > 0) {
          map.value.fitBounds(earthquakeLayer.getBounds())
        }
        
      } catch (err) {
        error.value = err.message
        console.error('Error fetching earthquake data:', err)
      } finally {
        loading.value = false
      }
    }
    
    // 初始化地图
    const initMap = () => {
      map.value = L.map(mapContainer.value).setView([30, 0], 2)
      
      L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
        attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
      }).addTo(map.value)
      
      // 添加图例
      addLegend()
    }
    
    // 组件挂载时执行
    onMounted(() => {
      // 创建粒子背景
      createParticles()
      
      // 初始化地图
      initMap()
      
      // 获取地震数据
      fetchEarthquakeData()
      
      // 每5分钟自动刷新数据
      refreshInterval = setInterval(fetchEarthquakeData, 300000)
    })
    
    // 组件卸载时清理
    onUnmounted(() => {
      if (refreshInterval) {
        clearInterval(refreshInterval)
      }
    })
    
    return {
      mapContainer,
      particlesContainer,
      earthquakeData,
      selectedEarthquake,
      loading,
      error,
      stats,
      formatTime,
      formatRelativeTime
    }
  }
}
</script>

<style>
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
  background: linear-gradient(135deg, #1a2a3a, #0d1b2a);
  color: #fff;
  min-height: 100vh;
  overflow-x: hidden;
}

.app {
  min-height: 100vh;
}

.header {
  background: rgba(0, 0, 0, 0.7);
  backdrop-filter: blur(10px);
  color: white;
  padding: 20px;
  text-align: center;
  box-shadow: 0 4px 30px rgba(0, 0, 0, 0.3);
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
  position: relative;
  overflow: hidden;
}

.header::before {
  content: "";
  position: absolute;
  top: -50%;
  left: -50%;
  width: 200%;
  height: 200%;
  background: radial-gradient(circle, rgba(52, 152, 219, 0.2) 0%, transparent 70%);
  animation: rotate 10s linear infinite;
  z-index: 0;
}

@keyframes rotate {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

.header h1 {
  font-size: 2.5rem;
  margin-bottom: 10px;
  background: linear-gradient(90deg, #3498db, #2ecc71, #e74c3c);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  text-shadow: 0 0 20px rgba(52, 152, 219, 0.3);
  position: relative;
  z-index: 1;
}

.header p {
  font-size: 1.2rem;
  opacity: 0.9;
  position: relative;
  z-index: 1;
}

#map {
  height: 65vh;
  width: 90%;
  margin: 20px auto;
  border-radius: 15px;
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.4);
  border: 1px solid rgba(255, 255, 255, 0.1);
  overflow: hidden;
}

.info-panel {
  max-width: 90%;
  width: 90%;
  margin: 0 auto 30px;
  padding: 25px;
  background: rgba(30, 30, 46, 0.8);
  border-radius: 15px;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
  backdrop-filter: blur(10px);
  border: 1px solid rgba(255, 255, 255, 0.1);
  animation: fadeIn 0.5s ease-out;
}

@keyframes fadeIn {
  from {
    opacity: 0;
    transform: translateY(20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.info-panel h2 {
  color: #3498db;
  margin-bottom: 15px;
  border-bottom: 2px solid rgba(52, 152, 219, 0.5);
  padding-bottom: 10px;
  font-size: 1.8rem;
}

.earthquake-marker {
  border: none;
  border-radius: 50%;
  background: #e74c3c;
  opacity: 0.8;
  transition: all 0.3s ease;
  box-shadow: 0 0 10px currentColor;
  animation: pulse 2s infinite;
}

@keyframes pulse {
  0% {
    transform: scale(1);
    box-shadow: 0 0 0 0 rgba(231, 76, 60, 0.7);
  }
  70% {
    transform: scale(1.05);
    box-shadow: 0 0 0 10px rgba(231, 76, 60, 0);
  }
  100% {
    transform: scale(1);
    box-shadow: 0 0 0 0 rgba(231, 76, 60, 0);
  }
}

.earthquake-marker:hover {
  opacity: 1;
  transform: scale(1.2);
  box-shadow: 0 0 20px currentColor;
}

.magnitude-popup .leaflet-popup-content-wrapper {
  border-radius: 12px;
  background: rgba(30, 30, 46, 0.95);
  color: white;
  backdrop-filter: blur(5px);
  border: 1px solid rgba(52, 152, 219, 0.5);
  box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
}

.magnitude-popup .leaflet-popup-tip {
  background: rgba(30, 30, 46, 0.95);
  border: 1px solid rgba(52, 152, 219, 0.5);
}

.magnitude-info h3 {
  margin: 0 0 15px 0;
  font-size: 1.4rem;
  color: #3498db;
  text-align: center;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
  padding-bottom: 10px;
}

.magnitude-info p {
  margin: 10px 0;
  font-size: 1.1rem;
  display: flex;
  justify-content: space-between;
}

.magnitude-info p span:first-child {
  font-weight: bold;
  color: #3498db;
}

.magnitude-info .time {
  color: #ecf0f1;
  font-weight: bold;
}

.magnitude-info .magnitude {
  font-size: 2rem;
  font-weight: bold;
  text-align: center;
  background: linear-gradient(90deg, #e74c3c, #f39c12);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  margin: 15px 0;
  text-shadow: 0 0 10px rgba(231, 76, 60, 0.3);
}

.magnitude-info .place {
  font-style: italic;
  color: #bdc3c7;
  text-align: center;
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid rgba(255, 255, 255, 0.1);
}

.loading {
  text-align: center;
  padding: 30px;
  font-size: 1.3rem;
  color: #3498db;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.loading::after {
  content: "";
  width: 30px;
  height: 30px;
  border: 3px solid rgba(52, 152, 219, 0.3);
  border-top: 3px solid #3498db;
  border-radius: 50%;
  animation: spin 1s linear infinite;
  margin-top: 15px;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

.error {
  background: rgba(231, 76, 60, 0.2);
  color: #e74c3c;
  padding: 20px;
  border-radius: 10px;
  margin: 20px;
  text-align: center;
  border: 1px solid rgba(231, 76, 60, 0.5);
  backdrop-filter: blur(5px);
}

.legend {
  background: rgba(30, 30, 46, 0.9);
  padding: 15px;
  border-radius: 10px;
  box-shadow: 0 0 15px rgba(0,0,0,0.3);
  backdrop-filter: blur(5px);
  border: 1px solid rgba(255, 255, 255, 0.1);
  color: #ecf0f1;
}

.legend h4 {
  margin: 0 0 12px;
  font-size: 1.2rem;
  color: #3498db;
  text-align: center;
}

.legend-item {
  display: flex;
  align-items: center;
  margin-bottom: 8px;
  padding: 5px;
  border-radius: 5px;
  transition: background 0.3s;
}

.legend-item:hover {
  background: rgba(52, 152, 219, 0.1);
}

.legend-color {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  margin-right: 12px;
  display: inline-block;
  box-shadow: 0 0 5px rgba(0,0,0,0.5);
}

.legend-label {
  font-size: 0.95rem;
}

.stats-panel {
  display: flex;
  justify-content: space-around;
  margin: 15px 0;
  flex-wrap: wrap;
}

.stat-card {
  background: rgba(52, 152, 219, 0.1);
  border-radius: 10px;
  padding: 15px;
  text-align: center;
  min-width: 150px;
  margin: 10px;
  border: 1px solid rgba(52, 152, 219, 0.3);
  transition: transform 0.3s;
}

.stat-card:hover {
  transform: translateY(-5px);
  background: rgba(52, 152, 219, 0.2);
}

.stat-card h3 {
  color: #3498db;
  margin-bottom: 8px;
  font-size: 1.1rem;
}

.stat-card .value {
  font-size: 1.8rem;
  font-weight: bold;
  background: linear-gradient(90deg, #3498db, #2ecc71);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
}

.particles-container {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: -1;
  pointer-events: none;
}

.particle {
  position: absolute;
  border-radius: 50%;
  background: rgba(52, 152, 219, 0.5);
  box-shadow: 0 0 10px rgba(52, 152, 219, 0.8);
  animation: float 15s infinite linear;
}

@keyframes float {
  0% {
    transform: translateY(0) translateX(0) rotate(0deg);
    opacity: 0;
  }
  10% {
    opacity: 1;
  }
  90% {
    opacity: 1;
  }
  100% {
    transform: translateY(-100vh) translateX(100px) rotate(360deg);
    opacity: 0;
  }
}

@media (max-width: 768px) {
  .stats-panel {
    flex-direction: column;
    align-items: center;
  }
  
  .stat-card {
    width: 80%;
    margin: 5px 0;
  }
  
  #map {
    height: 50vh;
  }
  
  .header h1 {
    font-size: 2rem;
  }
}
</style>